jetcrab\vm\heap/
garbage_collection.rs1use crate::vm::handle::HeapHandleId;
2use super::entries::HeapEntry;
3use super::types::HeapMetrics;
4use std::collections::{HashSet, HashMap};
5use std::time::Instant;
6
7pub struct GarbageCollectorImpl {
8 metrics: HeapMetrics,
9 collection_count: usize,
10 total_collection_time: std::time::Duration,
11 last_collection_size: usize,
12}
13
14impl Clone for GarbageCollectorImpl {
15 fn clone(&self) -> Self {
16 Self {
17 metrics: self.metrics.clone(),
18 collection_count: self.collection_count,
19 total_collection_time: self.total_collection_time,
20 last_collection_size: self.last_collection_size,
21 }
22 }
23}
24
25impl GarbageCollectorImpl {
26 pub fn new() -> Self {
27 Self {
28 metrics: HeapMetrics::new(),
29 collection_count: 0,
30 total_collection_time: std::time::Duration::ZERO,
31 last_collection_size: 0,
32 }
33 }
34
35 pub fn get_metrics(&self) -> &HeapMetrics {
36 &self.metrics
37 }
38
39 pub fn get_metrics_mut(&mut self) -> &mut HeapMetrics {
40 &mut self.metrics
41 }
42
43 pub fn mark_and_sweep(&mut self, roots: &[HeapHandleId]) -> usize {
45 let marked = self.mark_phase(roots);
46 self.sweep_phase(&marked)
47 }
48
49 pub fn mark_phase(&mut self, roots: &[HeapHandleId]) -> HashSet<usize> {
50 let mut marked = HashSet::new();
51 let mut to_visit = Vec::new();
52
53 for root in roots {
55 to_visit.push(root.as_usize());
56 }
57
58 while let Some(index) = to_visit.pop() {
60 if marked.insert(index) {
61 if let Some(entry) = self.get_entry(index) {
64 match entry {
65 HeapEntry::Object(obj) => {
66 for value in obj.values() {
68 if let Some(handle) = self.extract_handle(value) {
69 to_visit.push(handle.as_usize());
70 }
71 }
72 }
73 HeapEntry::Array(arr) => {
74 for value in arr {
76 if let Some(handle) = self.extract_handle(value) {
77 to_visit.push(handle.as_usize());
78 }
79 }
80 }
81 HeapEntry::Function { closure_vars, .. } => {
82 for value in closure_vars.values() {
84 if let Some(handle) = self.extract_handle(value) {
85 to_visit.push(handle.as_usize());
86 }
87 }
88 }
89 _ => {}
90 }
91 }
92 }
93 }
94
95 marked
96 }
97
98 pub fn sweep_phase(&mut self, marked: &HashSet<usize>) -> usize {
99 let mut collected = 0;
100
101 for index in 0..self.get_entry_count() {
104 if !marked.contains(&index) {
105 self.mark_as_deallocated(index);
107 collected += 1;
108 }
109 }
110
111 collected
112 }
113}
114
115impl super::management::GarbageCollector for GarbageCollectorImpl {
116 fn collect_garbage(&mut self, _entries: &mut HashMap<HeapHandleId, HeapEntry>, roots: &[HeapHandleId]) -> usize {
117 let start_time = Instant::now();
118 let collected = self.mark_and_sweep(roots);
119 let duration = start_time.elapsed();
120
121 self.collection_count += 1;
122 self.total_collection_time += duration;
123 self.last_collection_size = collected;
124 self.metrics.record_gc_cycle(duration);
125
126 collected
127 }
128
129 fn get_collection_stats(&self) -> (usize, u32, u32) {
130 (
131 self.collection_count,
132 self.total_collection_time.as_millis() as u32,
133 self.last_collection_size as u32
134 )
135 }
136}
137
138impl Default for GarbageCollectorImpl {
139 fn default() -> Self {
140 Self::new()
141 }
142}
143
144impl GarbageCollectorImpl {
146 fn get_entry(&self, _index: usize) -> Option<&HeapEntry> {
147 None
149 }
150
151 fn get_entry_count(&self) -> usize {
152 0
154 }
155
156 fn mark_as_deallocated(&mut self, _index: usize) {
157 }
159
160 fn extract_handle(&self, _value: &crate::vm::value::Value) -> Option<HeapHandleId> {
161 None
163 }
164}
165
166#[derive(Debug, Clone, Copy)]
167pub struct GarbageCollectionStats {
168 pub collection_count: usize,
169 pub total_collection_time: std::time::Duration,
170 pub last_collection_size: usize,
171 pub average_collection_time: std::time::Duration,
172}
173
174impl GarbageCollectionStats {
175 pub fn new() -> Self {
176 Self {
177 collection_count: 0,
178 total_collection_time: std::time::Duration::ZERO,
179 last_collection_size: 0,
180 average_collection_time: std::time::Duration::ZERO,
181 }
182 }
183}
184
185impl Default for GarbageCollectionStats {
186 fn default() -> Self {
187 Self::new()
188 }
189}